/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ships.core.icc;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author fqhuy
 */
public class IccIO {

    public static enum icSeekVal {

        icSeekSet, //Seek to an absolute position
        icSeekCur, //Seek to relative position
        icSeekEnd,     //Seek relative to the ending
    }

    public static interface CIccIO {

        public void Close();

        public byte[] Read8(int nNum) throws IOException;

        public int Write8(Object pBuf8, int nNum);

        public int ReadLine(Object pBuf8, int nNum);

        public short[] Read16(int nNum) throws IOException;

        public int Write16(Object pBuf16, int nNum);

        public int[] Read32(int nNum) throws IOException;

        public int Write32(Object pBuf32, int nNum);

        public long[] Read64(int nNum) throws IOException;

        public int Write64(Object pBuf64, int nNum);

        public int Read8Float(Object pBufFloat, int nNum);

        public int Write8Float(Object pBuf16, int nNum);

        public int Read16Float(Object pBufFloat, int nNum);

        public int Write16Float(Object pBuf16, int nNum);

        public int ReadFloat32Float(Object pBufFloat, int nNum);

        public int WriteFloat32Float(Object pBufFloat, int nNum);

        public int GetLength();

        public int Seek(int nOffset, icSeekVal pos);

        public int Tell();

        ///Write operation to make sure that filelength is evenly divisible by 4
        boolean Align32();

        ///Operation to make sure read position is evenly divisible by 4
        boolean Sync32(int nOffset);
    }

    public static class CIccFileIO implements CIccIO {

        protected File m_fFile;
        protected FileInputStream m_fFileStream;
        protected DataInputStream m_fDataStream;
        protected FileChannel m_fFileChannel;

        public CIccFileIO() {
            
        }
        public CIccFileIO(InputStream is) {
            //super(is);
        }

        public boolean Open(String szFilename, String szAttr) {
            m_fFile = new File(szFilename);
            try {
                m_fFileStream = new FileInputStream(m_fFile);
                // throw new UnsupportedOperationException();
            } catch (FileNotFoundException ex) {
                Logger.getLogger(IccIO.class.getName()).log(Level.SEVERE, null, ex);
                return false;
            }
            m_fDataStream = new DataInputStream(m_fFileStream);
            m_fFileChannel = m_fFileStream.getChannel();
            return true;
        }

        @Override
        public void Close() {
            try {

                m_fFileStream.close();
                m_fDataStream.close();
            } catch (IOException ex) {
                Logger.getLogger(IccIO.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        @Override
        public byte[] Read8(int nNum) throws IOException {
            byte[] pBuf = new byte[nNum];
            m_fDataStream.read((byte[]) pBuf);

            return pBuf;
        }

        @Override
        public int Write8(Object pBuf, int nNum) {

            //throw new UnsupportedOperationException();

            return 0;
        }

        @Override
        public int GetLength() {
            return (int) m_fFile.length();
            //throw new UnsupportedOperationException();
        }

        @Override
        public int Seek(int nOffset, icSeekVal pos) {
            switch (pos) {
                case icSeekSet:
                    try {
                        m_fFileChannel.position(nOffset);
                    } catch (IOException ex) {
                        Logger.getLogger(IccIO.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    break;
                case icSeekCur:
                    try {
                        m_fDataStream.skip(nOffset);
                    } catch (IOException ex) {
                        Logger.getLogger(IccIO.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    break;
                case icSeekEnd:
                    try {
                        m_fFileChannel.position(m_fFile.length());
                    } catch (IOException ex) {
                        Logger.getLogger(IccIO.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    break;
                default:

                    break;
            }

            return 0;
            //throw new UnsupportedOperationException();
        }

        @Override
        public int Tell() {
            try {
                return (int) m_fFileChannel.position();
                //throw new UnsupportedOperationException();
            } catch (IOException ex) {
                Logger.getLogger(IccIO.class.getName()).log(Level.SEVERE, null, ex);
            }
            return -1;
        }

        public int ReadLine(Object pBuf8, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public short[] Read16(int nNum) throws IOException{
            short[] re = new short[nNum];
            for (int i = 0; i < nNum; i++) {
                re[i] = m_fDataStream.readShort();
            }
            return re;
        }

        public int Write16(Object pBuf16, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int[] Read32(int nNum) throws IOException {
            int[] re = new int[nNum];
            for (int i = 0; i < nNum; i++) {
                re[i] = m_fDataStream.readInt();
            }
            return re;
            //throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write32(Object pBuf32, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public long[] Read64(int nNum) throws IOException{
             long[] re = new long[nNum];
            for (int i = 0; i < nNum; i++) {
                re[i] = m_fDataStream.readLong();
            }
            return re;
        }

        public int Write64(Object pBuf64, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Read8Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write8Float(Object pBuf16, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Read16Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write16Float(Object pBuf16, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int ReadFloat32Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int WriteFloat32Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean Align32() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean Sync32(int nOffset) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    public static class CIccMemIO  implements CIccIO {

        public CIccMemIO(InputStream is) {
            //super(is);
        }

        public boolean Alloc(int nSize, boolean bWrite) {
            throw new UnsupportedOperationException();
        }

        public boolean Attach(byte[] pData, int nSize, boolean bWrite) {
            throw new UnsupportedOperationException();
        }

        public void Close() {
            throw new UnsupportedOperationException();
        }

        public int Read8(Object pBuf, int nNum) {
            throw new UnsupportedOperationException();
        }

        public int Write8(Object pBuf, int nNum) {
            throw new UnsupportedOperationException();
        }

        public int GetLength() {
            throw new UnsupportedOperationException();
        }

        public int Seek(int nOffset, icSeekVal pos) {
            throw new UnsupportedOperationException();
        }

        public int Tell() {
            throw new UnsupportedOperationException();
        }

        byte[] GetData() {
            return m_pData;
        }
        protected byte[] m_pData;
        protected int m_nSize;
        protected int m_nAvail;
        protected int m_nPos;
        protected boolean m_bFreeData;

        public byte[] Read8(int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int ReadLine(Object pBuf8, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public short[] Read16( int nNum) throws IOException{
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write16(Object pBuf16, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int[] Read32(int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write32(Object pBuf32, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public long[] Read64(int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write64(Object pBuf64, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Read8Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write8Float(Object pBuf16, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Read16Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int Write16Float(Object pBuf16, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int ReadFloat32Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int WriteFloat32Float(Object pBufFloat, int nNum) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean Align32() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean Sync32(int nOffset) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
}
